﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using SST.WebClient.Data;
using SST.WebClient.Util;
using System.Text;
using System.Text.RegularExpressions;

namespace SST.WebClient
{
    /// <summary>
    /// Provide now playing information
    /// Contains parser logic to convert html to information object
    /// </summary>
    public class NowPlayingInfo
    {
        public event EventHandler<NowPlayingInfoGetAsyncEventArgs> GetAsyncCompleted;

        /// <summary>
        /// Get current request information
        /// </summary>
        /// <returns></returns>
        public void GetAsync()
        {
            Helper helper = new Helper();
            helper.DownloadWebpageAsyncCompleted += (s, e) =>
            {
                //begin parsing
                Soundtrack track = new Soundtrack();
                StreamingRequest request = new StreamingRequest()
                {
                    Track = track
                };
                try
                {
                    using (StringReader reader = new StringReader(e.Html))
                    {
                        bool isMarkerReached = false;
                        #region Album Cover Start
                        do
                        {
                            string tmp = reader.ReadLine();
                            if (tmp == null)
                                break;
                            if (tmp.ToUpper().Contains("ALBUM COVER START"))
                            {
                                isMarkerReached = true;
                                break;
                            }
                        } while (reader.Peek() != -1);

                        if (isMarkerReached)
                        {
                            reader.ReadLine();

                            //album url
                            //<a href="modules.php?name=Album&asin=Lump_Sugar" target="_top">
                            string tmp = reader.ReadLine();
                            if (tmp != null)
                            {
                                Regex rgx = new Regex("<a href=\"" //start of <a> tag with href="
                                    + "([^\"\r\n]+)" //contain characters except double quote and end of line
                                    + "\" .*" //end with double quote
                                    , RegexOptions.Compiled);
                                Match m = rgx.Match(tmp.Trim());
                                if (m.Success && m.Groups.Count == 2)
                                    track.AlbumUrl = Common.SST_URL + "/" + m.Groups[1].Value;
                            }
                            Helper.Debug("track.AlbumUrl=" + track.AlbumUrl);

                            //<img src="/images/cover/Lump_Sugar.jpg" width="200" height="200" border="0" alt="View Album Info" >
                            tmp = reader.ReadLine();
                            if (tmp != null)
                            {
                                Regex rgx = new Regex("<img src=\"" //start of <img> tag with href="
                                    + "([^\"\r\n]+)" //contain characters except double quote and end of line
                                    + "\" .*" //end with double quote
                                    , RegexOptions.Compiled);
                                Match m = rgx.Match(tmp.Trim());
                                if (m.Success && m.Groups.Count == 2)
                                {
                                    track.AlbumArt = m.Groups[1].Value;
                                    if (track.AlbumArt != null && track.AlbumArt.Length > 0)
                                        track.AlbumArt = Common.SST_URL + track.AlbumArt;
                                }
                            }
                            Helper.Debug("track.AlbumArt=" + track.AlbumArt);
                        }
                        #endregion

                        #region Song Info Cell Start
                        isMarkerReached = false;
                        do
                        {
                            string tmp = reader.ReadLine();
                            if (tmp == null)
                                break;
                            if (tmp.ToUpper().Contains("SONG INFO CELL START"))
                            {
                                isMarkerReached = true;
                                break;
                            }
                        } while (reader.Peek() != -1);
                        if (isMarkerReached)
                        {
                            reader.ReadLine();
                            reader.ReadLine();
                            //<a href="/modules.php?name=Album&asin=Lump_Sugar"
                            string tmp = reader.ReadLine();
                            if (tmp != null && tmp.ToUpper().Contains("MODULES.PHP"))
                            {
                                Regex rgx = new Regex("<a[^>]+>" //<a> start tag
                                    + "([^<]+)" //contain characters except <, Album name
                                    + "</a>[^<]+" //</a> end tag, and characters exception <
                                    + "<a[^>]+>" //<a> start tag
                                    + "([^<]+)" //contain characters except <, artist
                                    + "</a><br>" //</a> end tag and <br>
                                    + "([^<]+)" //contain characters except <, Track title, but need to remove the last open bracket manually
                                    , RegexOptions.Compiled);
                                Match m = rgx.Match(tmp);
                                if (m.Success && m.Groups.Count == 4)
                                {
                                    track.Album = m.Groups[1].Value.Trim();
                                    track.Artist = m.Groups[2].Value.Trim();
                                    track.Title = m.Groups[3].Value.Trim();
                                    track.Title = track.Title.Substring(0, track.Title.Length - 1).Trim();
                                    Helper.Debug("track.Album=" + track.Album);
                                    Helper.Debug("track.Artist=" + track.Artist);
                                    Helper.Debug("track.Title=" + track.Title);
                                }
                            }
                        }
                        #endregion

                        #region Countdown timer
                        isMarkerReached = false;
                        string countDownLine = null;
                        do
                        {
                            string tmp = reader.ReadLine();
                            if (tmp == null)
                                break;
                            if (tmp.ToUpper().Contains("COUNTDOWNTIME"))
                            {
                                isMarkerReached = true;
                                countDownLine = tmp;
                                break;
                            }
                        } while (reader.Peek() != -1);
                        if (isMarkerReached && countDownLine != null)
                        {
                            Regex rgx = new Regex("= " //equal sign and a space character
                                + "([0-9]+)" //the number, seconds left of the track
                                , RegexOptions.Compiled);
                            Match m = rgx.Match(countDownLine);
                            if (m.Success && m.Groups.Count == 2)
                                track.Duration = int.Parse(m.Groups[1].Value);
                            Helper.Debug("track.Duration=" + track.Duration.ToString());
                        }
                        #endregion

                        #region Request By:
                        isMarkerReached = false;
                        do
                        {
                            string tmp = reader.ReadLine();
                            if (tmp == null)
                                break;
                            if (tmp.ToUpper().Contains("REQUEST BY:"))
                            {
                                isMarkerReached = true;
                                break;
                            }
                        } while (reader.Peek() != -1);
                        if (isMarkerReached)
                        {
                            string tmp = reader.ReadLine();
                            //detect system/admin
                            if (tmp.Contains("</b><i>System/Admin</i>"))
                            {
                                request.Requester = "System/Admin";
                                request.IsRequestByAdmin = true;
                            }
                            else
                            {
                                //check if vip, because markup will be different
                                if (tmp.Contains("</div>"))
                                {
                                    //non vip logic
                                    string[] tmpArray = tmp.Split('-');
                                    request.Requester = tmpArray[0].Replace("</div>", "").Trim();
                                    if (tmpArray.Length > 1)
                                        request.Comment = tmpArray[1].Replace("</div>", "").Trim();
                                }
                                else
                                {
                                    //vip logic
                                    request.Requester = tmp.Trim();

                                    tmp = reader.ReadLine();
                                    Regex rgx = new Regex("</a> - " //end of </a> and a space, hyphen, a space
                                        + "([^<]+)" //characters except <
                                        , RegexOptions.Compiled);
                                    Match m = rgx.Match(tmp);
                                    if (m.Success && m.Groups.Count == 2)
                                        request.Comment = m.Groups[1].Value.Trim();
                                }
                            }
                            Helper.Debug("request.Requester=" + request.Requester);
                            Helper.Debug("request.Comment=" + request.Comment);
                        }

                        #endregion
                    }
                    OnGetAsyncCompleted(new NowPlayingInfoGetAsyncEventArgs(request));
                }
                catch (Exception ex)
                {
                    Helper.Debug(ex);
                }
            };
            helper.DownloadWebpageAsync("http://www.streamingsoundtracks.com/playing.php?rand=" + DateTime.Now.Ticks);
            //helper.DownloadWebpageAsync("http://10.0.1.106:8056/~sloth/detect.php");
        }

        // Wrap event invocations inside a protected virtual method
        // to allow derived classes to override the event invocation behavior
        protected virtual void OnGetAsyncCompleted(NowPlayingInfoGetAsyncEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of
            // a race condition if the last subscriber unsubscribes
            // immediately after the null check and before the event is raised.
            EventHandler<NowPlayingInfoGetAsyncEventArgs> handler = GetAsyncCompleted;

            // Event will be null if there are no subscribers
            if (handler != null)
            {
                // Use the () operator to raise the event.
                System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => { handler(this, e); });
            }
        }
    }
    
    /// <summary>
    /// Contains current streaming request
    /// </summary>
    public class NowPlayingInfoGetAsyncEventArgs : EventArgs
    {
        private StreamingRequest _request;

        public StreamingRequest Request
        {
            get { return _request; }
            set { _request = value; }
        }

        public NowPlayingInfoGetAsyncEventArgs(StreamingRequest request)
        {
            this._request = request;
        }
    }
}
